<?php
/**
 * Created by PhpStorm.
 * User: yanwenqing
 * Date: 2018/8/14
 * Time: 18:46
 */
namespace Home\Service;

class ClientService{

    public $ticket;
    public $_url;
    public $loginUrl;
    public $serverBaseUrl = 'http://www.auths.com/api';
    public $server = 'http://www.auths.com';
    public $user;

    public function __construct()
    {
        $ticket = (isset($_GET['ticket']) ? $_GET['ticket'] : null);
        if(preg_match('/^[SP]T-/', $ticket)){
            $this->ticket = $ticket;
            unset($_GET['ticket']);
        }
    }

    public function setLoginUrl(){
        $server = 'http://www.auths.com'; // cas服务端的地址

        $loginUrl = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        $this->loginUrl = $server.'/cas/login?service='.urlencode($loginUrl);
    }

    public function getUrl(){
        if ( empty($this->_url) ) {
            $final_uri = ($this->_isHttps()) ? 'https' : 'http';
            $final_uri .= '://';

            $final_uri .= $this->_getClientUrl();
            $request_uri	= explode('?', $_SERVER['REQUEST_URI'], 2);
            $final_uri		.= $request_uri[0];

            if (isset($request_uri[1]) && $request_uri[1]) {
                $query_string= $this->_removeParameterFromQueryString('ticket', $request_uri[1]);
                if ($query_string !== '') {
                    $final_uri	.= "?$query_string";
                }
            }
            $this->setURL($final_uri);
        }

        return $this->_url;
    }

    /**
     * 设置url
     * @param $url
     */
    protected function setURL($url){
        $this->_url = $url;
    }

    private function _isHttps()
    {
        if (!empty($_SERVER['HTTP_X_FORWARDED_PROTO'])) {
            return ($_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https');
        } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTOCOL'])) {
            return ($_SERVER['HTTP_X_FORWARDED_PROTOCOL'] === 'https');
        } elseif ( isset($_SERVER['HTTPS'])
            && !empty($_SERVER['HTTPS'])
            && strcasecmp($_SERVER['HTTPS'], 'off') !== 0
        ) {
            return true;
        }
        return false;

    }

    private function _getClientUrl()
    {
        if (!empty($_SERVER['HTTP_X_FORWARDED_HOST'])) {
            // explode the host list separated by comma and use the first host
            $hosts = explode(',', $_SERVER['HTTP_X_FORWARDED_HOST']);
            // see rfc7239#5.3 and rfc7230#2.7.1: port is in HTTP_X_FORWARDED_HOST if non default
            return $hosts[0];
        } else if (!empty($_SERVER['HTTP_X_FORWARDED_SERVER'])) {
            $server_url = $_SERVER['HTTP_X_FORWARDED_SERVER'];
        } else {
            if (empty($_SERVER['SERVER_NAME'])) {
                $server_url = $_SERVER['HTTP_HOST'];
            } else {
                $server_url = $_SERVER['SERVER_NAME'];
            }
        }
        if (!strpos($server_url, ':')) {
            if (empty($_SERVER['HTTP_X_FORWARDED_PORT'])) {
                $server_port = $_SERVER['SERVER_PORT'];
            } else {
                $ports = explode(',', $_SERVER['HTTP_X_FORWARDED_PORT']);
                $server_port = $ports[0];
            }

            if ( ($this->_isHttps() && $server_port!=443)
                || (!$this->_isHttps() && $server_port!=80)
            ) {
                $server_url .= ':';
                $server_url .= $server_port;
            }
        }
        return $server_url;
    }

    private function _removeParameterFromQueryString($parameterName, $queryString)
    {
        $parameterName	= preg_quote($parameterName);
        return preg_replace(
            "/&$parameterName(=[^&]*)?|^$parameterName(=[^&]*)?&?/",
            '', $queryString
        );
    }

    /**
     * 验证ticket， 返回用户数据
     * @param $validate_url
     * @param $text_response
     * @param $tree_response
     * @param bool $renew
     * @return bool
     * @throws \Exception
     */
    public function validateCas(&$validate_url, &$text_response, &$tree_response, $renew=false){
        $validate_url = $this->getServerServiceValidateURL().'&ticket=' .urlencode($this->getTicket());
        if($renew){
            $validate_url .= '&renew=true';
        }
        $re = $this->curl_request($validate_url);
        $reArr = json_decode($re, true);
        if(empty($reArr) || (array_key_exists('status', $reArr) && empty($re['status']))){
            throw new \Exception('ticket invalid !');
        }
        $this->user = $reArr;

        return true;
    }

    public function serveLogout(){
        $this->serverBaseUrl.'/cas/logout';
    }

    /**
     * 封装cur请求
     * post数据(不填则为GET)，参数3：提交的$cookies,参数4：是否返回$cookies
     * @param $url
     * @param string $post
     * @param string $cookie
     * @param int $returnCookie
     * @return mixed|string
     */
    public function curl_request($url,$post='',$cookie='', $returnCookie=0){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
        curl_setopt($curl, CURLOPT_REFERER, "http://XXX");
        if($post) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
        }
        if($cookie) {
            curl_setopt($curl, CURLOPT_COOKIE, $cookie);
        }
        curl_setopt($curl, CURLOPT_HEADER, $returnCookie);
        curl_setopt($curl, CURLOPT_TIMEOUT, 10);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $data = curl_exec($curl);
        if (curl_errno($curl)) {
            return curl_error($curl);
        }
        curl_close($curl);
        if($returnCookie){
            list($header, $body) = explode("\r\n\r\n", $data, 2);
            preg_match_all("/Set\-Cookie:([^;]*);/", $header, $matches);
            $info['cookie']  = substr($matches[1][0], 1);
            $info['content'] = $body;
            return $info;
        }else{
            return $data;
        }
    }

    public function getServerServiceValidateURL(){
        $url = $this->_getServerBaseURL() .'/serviceValidate';
        return $this->_buildQueryUrl($url, 'service='.urlencode($this->getUrl()));
    }

    protected function _getServerBaseURL(){
        return $this->serverBaseUrl;
    }

    private function _buildQueryUrl($url, $query){
        $url .= (strstr($url, '?') === false) ? '?' : '&';
        $url .= $query;
        return $url;
    }

    public function getTicket(){
        return $this->ticket;
    }
}